/*	--- 使用AOP --- 

【AOP】 是 【Aspect Oriented Programming】，即【面向切面编程】。
	Aspect  n.  方面, 面, 侧面
	Oriented  v. 面向

那什么是AOP？

----------------------------------------------

我们先回顾一下
	OOP：Object Oriented Programming

【OOP】作为【面向对象编程的模式】，获得了巨大的成功

【OOP的主要功能】是【数据封装、继承、多态】。

-------------------------------------------

而AOP是一种新的编程方式，它和OOP不同，【OOP】把【系统】看作【多个对象的交互】，【AOP】把【系统】分解为【不同的关注点】，或者称之为【切面/片面】（Aspect）。


要理解AOP的概念，我们先用OOP举例，比如【一个业务组件 BookService】， 它有【几个业务方法】：

	· createBook：添加新的Book；
	· updateBook：修改Book；
	· deleteBook：删除Book。


对于【每个业务的Method】，例如，createBook()，除了【业务逻辑】，还需要【安全检查、日志记录、事务处理】

【OOP的代码】像这样： */
public class BookService {

	public void createBook(Book book) {
		securityCheck();

		Tansaction tx = startTransaction();
			// transaction n. 交易, 买卖, 合同 

		try {
			// 核心业务逻辑
			tx.commit();
		} catch (RuntimeException e) {
			tx.rollback();
			throw e;
		}

		log("created book: " + book);
	}
}


/*
继续编写 updateBook()，代码如下： */
public class BookService {
	public void updateBook(Book book) {
		securityCheck();

		Transaction tx = startTransaction();

		try {
			// 核心业务逻辑
			tx.commit();
		} catch (RuntimeException e) {
			tx.rollback();
			throw e;
		}

		log("updated book: " + book);
	}
}

/*
对于【安全检查、日志、事务等 复用的代码】， 它们会重复出现在【每个业务方法】中。

使用OOP，我们很难将这些【四处分散的代码】模块化。

--------------------------------------------


考察【业务模型】可以发现，【BookService关系】的是【自身的核心逻辑】，但【整个系统】还要求【关注安全检查、日志、事务等功能】

【这些重复的功能】实际上“横跨”【多个业务方法】，为了实现【这些功能】，不得不在【每个业务方法】上【重复编写代码】。

------------------------------------

【一种可行的方式】是【使用Proxy模式】，将【某个功能】使用【Method】代理完成

例如，【权限检查】，放入【Proxy】中： */
public class SecurityCheckBookService implements BookService {

	private final BookService target;
		// class SecurityCheckBookService对BookService进行Proxy

	public SecurityCheckBookService(BookService target) {
		this.target = target;
	}

	public void createBook(Book book) {
		securityCheck(); 
		target.createBook(book);
	}

	public void updateBook(Book book) {
		securityCheck();
		target.updateBook(book);
	}

	public void deleteBook(Book book) {
		securityCheck();
		target.deleteBook(book);
	}

	private void securityCheck() {
		//...
	}
}


/*
【这种方式-Proxy的缺点】是【比较麻烦】，必须先【抽取接口】(抽取BookService的各个方法接口)，然后，针对【每个方法】实现【Proxy】。

------------------------------------

另一种方法是，既然【SecurityCheckBookService的代码】都是【标准的Proxy样板代码】，不如把【权限检查 securityCheck(); 】视作【一种切面】（Aspect）

把【日志、事务】等, 也视为【切面】

然后，以【某种自动化的方式】，把【切面】织入到【核心逻辑】中，实现【Proxy模式】。


如果我们以【AOP的视角】来编写【上述业务】，可以依次实现：

	1. 【核心逻辑】，即BookService；
	2. 【切面逻辑】，即：
		2-1. 【权限检查的Aspect】；
		2-2. 【日志的Aspect】；
		2-3. 【事务的Aspect】。


然后，以某种方式，让【框架】来把【上述3个Aspect】以【Proxy】的方式“织入”到【核心逻辑 BookService】中

这样一来，就不必编写【复杂而冗长的Proxy模式】。


=========================================================


#	AOP原理


如何把【切面 Aspect】织入到【核心逻辑】中？

这正是【AOP】需要解决的问题。

换句话说，如果【客户端】获得了【BookService的引用】，当【调用bookService.createBook() 】时，如何对【调用方法】进行【拦截】，并在【拦截前后】进行【安全检查、日志、事务等】处理，就相当于完成了【所有业务功能】。



在【Java平台】上，对于【AOP的织入】，有【3种方式】：

	1. "编译期"：在编译时，由【编译器】把【切面调用】编译进【字节码】，【这种方式】需要定义【新的关键字】并扩展【编译器】，【AspectJ】就扩展了【Java编译器】，使用【关键字aspect】来实现【织入】；
	
	2. "类加载器"：在【目标类】被装载到【JVM】时，通过【一个特殊的类加载器】，对【目标类的字节码】重新“增强”；

	3. "运行期"：【目标对象】和【切面】都是【普通Java类】，通过【JVM的动态代理功能】或者【第三方库】实现【运行期动态织入】。


--------------------------------------


【最简单的方式】是【第三种】，【Spring的AOP实现】就是【基于JVM的动态代理】。

由于【JVM的动态代理】要求必须实现【接口】

如果一个【普通类】没有【业务接口】，就需要通过【CGLIB 或者 Javassist】这些第三方库实现。

【AOP技术】看上去比较神秘，但实际上，【它本质】就是一个【动态代理】，让我们把一些常用功能如【权限检查、日志、事务等】，从【每个业务方法中】剥离出来。

需要特别指出的是，【AOP】对于【解决特定问题】，例如【事务管理】非常有用

这是因为【分散在各处的事务代码】几乎是【完全相同的】，并且它们【需要的参数】（JDBC的Connection）也是【固定的】。

【另一些特定问题】，如【日志】，就【不那么容易实现】，因为日志虽然简单，但打印日志的时候，经常需要【捕获局部变量】，如果【使用AOP实现日志】，我们【只能输出固定格式的日志】，因此，使用AOP时，必须适合【特定的场景】。

# PS: AOP 常用于 替代"固定输出/输入"的代码(即机械化场景,非AOP莫属)


===================================================================


#	----- 使用AOP の 小结 -----
Aspect Oriented Programming



*/





























